package com.gearbox.core.task;

import com.gearbox.core.driver.AsHandler;
import com.gearbox.core.model.Node;
import com.gearbox.core.service.NodeService;
import com.huaweicloud.sdk.as.v1.model.ScalingGroupInstance;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class NodeHealthAuditTask {
    private static final Logger LOG = LoggerFactory.getLogger(NodeHealthAuditTask.class);

    @Autowired
    private NodeService nodeService;

    @Autowired
    private AsHandler asHandler;

    @Scheduled(initialDelay = 10L, fixedDelayString = "${task.health-audit-period}", timeUnit = TimeUnit.SECONDS)
    private void doTask() {
        try {
            LOG.info("do NodeHealthAuditTask begin");
            List<Node> nodes = nodeService.listUnstableNodes();
            LOG.info("list all nodes, nodes={}", nodes);
            removeAbnormalNodes(filterNodesNotInScalingGroup(nodes));
            LOG.info("do NodeHealthAuditTask end");
        } catch (Throwable e) {
            LOG.error("do NodeHealthAuditTask error", e);
        }
    }

    List<Node> filterNodesNotInScalingGroup(List<Node> nodes) {
        Map<String, ScalingGroupInstance> groupInstanceMap = asHandler.getNameMapGroupInstances();
        return nodes.stream()
            .filter(node -> !groupInstanceMap.containsKey(node.getName()))
            .collect(Collectors.toList());
    }

    void removeAbnormalNodes(List<Node> nodes) {
        if (nodes.isEmpty()) {
            return;
        }
        nodes.forEach(this::removeNodeIfDown);
    }

    void removeNodeIfDown(Node node) {
        if (!isNodeAbnormal(node)) {
            LOG.error("node:[{}] status isn't DOWN", node);
            return;
        }
        try {
            LOG.info("node:[{}] is abnormal, delete it!", node);
            nodeService.remove(node);
        } catch (Exception e) {
            LOG.error("delete slurm instance error", e);
        }
    }

    boolean isNodeAbnormal(Node node) {
        return node.getStatus() != null && node.getStatus().isAbnormal();
    }
}
